package org.fuys.coder.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.fuys.coder.infrastructure.model.dto.ActTakeResultDTO;
import org.fuys.coder.common.constants.ResultMessageConstants;
import org.fuys.coder.common.entity.Pair;
import org.fuys.coder.common.exception.BusinessException;
import org.fuys.coder.domain.act.lottery.model.req.act.LotteryActivityAddReq;
import org.fuys.coder.domain.act.lottery.model.vo.activity.LotteryActVO;
import org.fuys.coder.domain.act.lottery.repository.ILotteryActivityRepository;
import org.fuys.coder.common.entity.PageDTO;
import org.fuys.coder.infrastructure.dao.AwardRedemptionMapper;
import org.fuys.coder.infrastructure.dao.LotteryActMapper;
import org.fuys.coder.infrastructure.dao.LotteryTakeMapper;
import org.fuys.coder.infrastructure.model.po.AwardRedemption;
import org.fuys.coder.infrastructure.model.po.LotteryAct;
import org.fuys.coder.infrastructure.model.po.LotteryTake;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @projectName: fuys-low-coder
 * @package: org.fuys.coder.infrastructure.repository
 * @className: LotteryActivityRepository
 * @author: WangJing
 * @description: 活动仓储服务
 * @date: 2024/7/5 22:56
 * @version: 1.0
 */
@Service
public class LotteryActivityRepository extends ServiceImpl<LotteryActMapper, LotteryAct>
        implements ILotteryActivityRepository {

    @Resource
    private LotteryActMapper lotteryActMapper;

    @Resource
    private LotteryTakeMapper lotteryTakeMapper;

    @Resource
    private AwardRedemptionMapper awardRedemptionMapper;

    @Override
    public Long addLotteryActInfo(LotteryActivityAddReq req) {
        LotteryAct lotteryAct=new LotteryAct();
        lotteryAct.setActDesc(req.getDesc());
        lotteryAct.setActName(req.getActName());
        lotteryAct.setBeginTime(req.getBeginTime());
        lotteryAct.setEndTime(req.getEndTime());
        lotteryAct.setActCover(req.getCover());
        lotteryAct.setCreatorId(req.getCreatorId());
        lotteryAct.setTakeCount(req.getTakeCount());
        lotteryActMapper.insert(lotteryAct);
        return lotteryAct.getId();
    }

    @Override
    public LotteryActVO getById(Long actId,Integer state) {
        final LotteryAct lotteryAct = lotteryActMapper.selectOne(new LambdaQueryWrapper<LotteryAct>()
                .select(LotteryAct::getActName, LotteryAct::getActCover, LotteryAct::getActDesc,
                        LotteryAct::getBeginTime, LotteryAct::getEndTime, LotteryAct::getTakeCount)
                .eq(LotteryAct::getId, actId).eq(LotteryAct::getState, state));
        if(lotteryAct!=null){
            LotteryActVO vo = new LotteryActVO();
            vo.setActId(actId);
            vo.setCoverId(lotteryAct.getActCover());
            vo.setActName(lotteryAct.getActName());
            vo.setActDesc(lotteryAct.getActDesc());
            vo.setBeginTime(lotteryAct.getBeginTime());
            vo.setEndTime(lotteryAct.getEndTime());
            vo.setTakeCount(lotteryAct.getTakeCount());
            return vo;
        }
        return null;
    }

    @Override
    public List<LotteryActVO> getCurAct(int num) {
        Page<LotteryAct> page=new Page<>();
        page.setCurrent(1);
        page.setSize(num);
        final Page<LotteryAct> lotteryActPage = lotteryActMapper.selectPage(page, new LambdaQueryWrapper<LotteryAct>()
                .select(LotteryAct::getId,LotteryAct::getActName, LotteryAct::getActCover, LotteryAct::getActDesc,
                        LotteryAct::getBeginTime, LotteryAct::getEndTime, LotteryAct::getTakeCount)
                .eq(LotteryAct::getState, 1)
                .orderByDesc(LotteryAct::getBeginTime));
        final List<LotteryAct> records = lotteryActPage.getRecords();
        if(ObjectUtils.isEmpty(lotteryActPage)||ObjectUtils.isEmpty(records)){
            return null;
        }
        return records.stream().map(item -> {
            LotteryActVO vo = new LotteryActVO();
            vo.setActId(item.getId());
            vo.setCoverId(item.getActCover());
            vo.setActName(item.getActName());
            vo.setActDesc(item.getActDesc());
            vo.setBeginTime(item.getBeginTime());
            vo.setEndTime(item.getEndTime());
            vo.setTakeCount(item.getTakeCount());
            return vo;
        }).collect(Collectors.toList());

    }

    @Override
    public Pair<List<LotteryActVO>,Long> getPage(PageDTO pageDTO) {
        Page<LotteryAct> page=new Page<>();
        page.setCurrent(pageDTO.getCurPage());
        page.setSize(pageDTO.getPageNum());
        final Page<LotteryAct> pageResult = lotteryActMapper.selectPage(page, new LambdaQueryWrapper<LotteryAct>()
                .select(LotteryAct::getId,LotteryAct::getActName, LotteryAct::getActCover, LotteryAct::getActDesc,
                        LotteryAct::getBeginTime, LotteryAct::getEndTime, LotteryAct::getTakeCount)
                .eq(LotteryAct::getState, 1).orderByDesc(LotteryAct::getBeginTime));
        if(pageResult==null || pageResult.getRecords()==null){
            return null;
        }
        final List<LotteryActVO> collect = pageResult.getRecords().stream()
                .map(item -> {
                    LotteryActVO vo = new LotteryActVO();
                    vo.setActId(item.getId());
                    vo.setCoverId(item.getActCover());
                    vo.setActName(item.getActName());
                    vo.setActDesc(item.getActDesc());
                    vo.setBeginTime(item.getBeginTime());
                    vo.setEndTime(item.getEndTime());
                    vo.setTakeCount(item.getTakeCount());
                    return vo;
                }).collect(Collectors.toList());
        return new Pair<>(collect,pageResult.getTotal());
    }

    @Override
    public boolean checkUserTakeCount(Integer userId,Long actId) {
       ActTakeResultDTO actTakeResultDTO =
               lotteryActMapper.checkTakeCount(userId,actId);
       if(actTakeResultDTO.getEndTime().getTime()<System.currentTimeMillis()){
           throw new BusinessException(ResultMessageConstants.ACT_END);
       }
        return actTakeResultDTO.getUserCount() < actTakeResultDTO.getTakeCount();
    }

    @Override
    public Integer getStrategyId(Long actId) {
        final LotteryAct lotteryAct = lotteryActMapper.selectOne(new LambdaQueryWrapper<LotteryAct>()
                .select(LotteryAct::getStrategyId).eq(LotteryAct::getId, actId));
        if(lotteryAct==null){
            return null;
        }
        return lotteryAct.getStrategyId();
    }

    @Override
    public void addLotteryTakeRecord(Integer userId, Long actId, String code, Long awardId
            , Date expire,Integer type) {
        LotteryTake lotteryTake=new LotteryTake();
        lotteryTake.setActId(actId);
        lotteryTake.setUserId(userId);
        lotteryTake.setCreateTime(new Date());
        AwardRedemption awardRedemption=new AwardRedemption();
        awardRedemption.setAwardId(awardId);
        awardRedemption.setExpiredTime(expire);
        awardRedemption.setUserId(userId);
        awardRedemption.setRedemptionCode(code);
        awardRedemption.setAwardType(type);
        awardRedemptionMapper.insert(awardRedemption);
        lotteryTakeMapper.insert(lotteryTake);
    }
}
